package com.wesley.framework.protocol.dubbo;


import com.wesley.framework.Invocation;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * NettyClient
 *
 * @author WangPanYong
 * @since 2021/11/17 14:21
 */
public class NettyClient {
    public NettyClientHandler client = null;
    private NioEventLoopGroup group = null;
    private ChannelFuture channelFuture = null;
    private static final ExecutorService executorService = Executors.newCachedThreadPool();

    public void start(String host, int port) {
        client = new NettyClientHandler();
        group = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(group)
                 .channel(NioSocketChannel.class)
                 .option(ChannelOption.TCP_NODELAY, true)
                 .handler(new ChannelInitializer<SocketChannel>() {
                     @Override
                     protected void initChannel(SocketChannel ch) throws Exception {
                         ChannelPipeline pipeline = ch.pipeline();
                         pipeline.addLast("handler", client);
                     }
                 });

        try {
            Thread thread = Thread.currentThread();
            channelFuture = bootstrap.connect(host, port).sync();
            System.out.println("【"+ thread.getName() + "】 Netty Client 启动 ...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public String send(String hostName, Integer port, Invocation invocation) {
        // 客户端处理器为空，启动客户端
        if (client == null) {
            start(hostName, port);
        }
        client.setInvocation(invocation);

        try {
            // 启动一个新的线程 发送数据，然后同步等待结果
            return (String) executorService.submit(client).get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        } finally {
            channelFuture.channel().closeFuture();
            group.shutdownGracefully();
        }

        return client.getResult();
    }
}
